package com.xbongbong.saas.help;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.SizeConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.AddressEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.enums.StarEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.CustomerRulePojo;
import com.xbongbong.paas.pojo.CustomerRuleTypePojo;
import com.xbongbong.paas.pojo.PublicRuleLabelPojo;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.domain.entity.LabelEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.domain.entity.UpdateDataValueEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.CustomerRuleConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ClueRuleEntity;
import com.xbongbong.saas.domain.entity.CustomerRuleEntity;
import com.xbongbong.saas.domain.entity.PublicGroupSeniorEntity;
import com.xbongbong.saas.domain.entity.RuleSeniorEntity;
import com.xbongbong.saas.domain.entity.TagEntity;
import com.xbongbong.saas.domain.entity.TagLinkEntity;
import com.xbongbong.saas.domain.entity.TransferBackRuleSeniorEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.enums.ClueChildTypeEnum;
import com.xbongbong.saas.enums.ClueRuleEnum;
import com.xbongbong.saas.enums.ClueSeniorBackChildEnum;
import com.xbongbong.saas.enums.ClueSeniorRuleTypeEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.CustomerChildTypeEnum;
import com.xbongbong.saas.enums.CustomerRuleEnum;
import com.xbongbong.saas.enums.CustomerSeniorBackChildEnum;
import com.xbongbong.saas.enums.CustomerSeniorRuleTypeEnum;
import com.xbongbong.saas.enums.SeniorFixedGroupEnum;
import com.xbongbong.saas.enums.TagTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.model.ClueRuleModel;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerRuleModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.LabelModel;
import com.xbongbong.saas.model.PublicGroupSeniorModel;
import com.xbongbong.saas.model.TagLinkModel;
import com.xbongbong.saas.model.TagModel;
import com.xbongbong.saas.model.TransferBackRuleSeniorModel;
import com.xbongbong.saas.model.impl.ClueModelImpl;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.RoleEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.RoleModel;
import com.xbongbong.sys.model.UserModel;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 高级公海模式的帮助类
 * @author 杨磊
 * @version v1.0
 * @since v1.0
 */
@Component
public class PublicSeniorRuleHelp {


    private static final Logger LOG = LoggerFactory.getLogger(PublicSeniorRuleHelp.class);


    @Resource
    private TransferBackRuleSeniorModel transferBackRuleSeniorModel;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private RoleModel roleModel;
    @Resource
    private UserModel userModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private CustomerRuleModel customerRuleModel;
    @Resource
    private ClueRuleModel clueRuleModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private LabelModel labelModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private TagLinkModel tagLinkModel;
    @Resource
    private TagModel tagModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private ContractModel contractModel;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private ClueModelImpl clueModel;
    @Resource
    private PublicGroupSeniorModel publicGroupSeniorModel;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;

    /**
     * 用来同步更新数据库和ES，用来同步所属分组用
     * @return
     */
    public void updateBatch(Integer businessType, String corpid, List<UpdateDataEntity> updateDataEntityList) throws XbbException {
        if (Objects.equals(businessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
            customerModel.updateBatch(updateDataEntityList, corpid);
        } else {
            clueModel.updateBatch(updateDataEntityList, corpid);
        }
    }


        /**
         * 客户星级数据封装
         *
         * @param isSort
         * @return
         */
    public List<CustomerRulePojo> getImportantDegree(boolean isSort) {
        List<CustomerRulePojo> rulePojoList = new ArrayList<>();
        for (StarEnum type : StarEnum.values()) {
            if (type == StarEnum.UNKNOW || type == StarEnum.ZERO) {
                continue;
            }
            CustomerRulePojo rulePojo = new CustomerRulePojo();
            rulePojo.setKey(String.valueOf(type.getValue()));
            if (StarEnum.ONE.getValue() == type.getValue()) {
                if (isSort) {
                    rulePojo.setValue(StarEnum.getStarByValue(type.getValue()).getText());
                } else {
                    rulePojo.setValue(I18nMessageUtil.getMessage(CustomerRuleConstant.ONE_AND_MORE_STAR));
                }
            } else {
                rulePojo.setValue(type.getText());
            }
            rulePojoList.add(rulePojo);
        }
        return rulePojoList;
    }

    /**
     * 规则的子类型选项
     *
     * @author 杨磊
     * @date 2012/4/28 16:47
     * @since v1.0
     */
    public List<CustomerRuleTypePojo> getChildTypeList(boolean numRule, Integer businessType) {
        List<CustomerRuleTypePojo> typeList = new ArrayList<>();
        if(Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
            for (CustomerChildTypeEnum type : CustomerChildTypeEnum.values()) {
                if (type == CustomerChildTypeEnum.UNKNOWN) {
                    continue;
                }

                //最大客户数规则没有根据客户状态设置
                if (numRule && type == CustomerChildTypeEnum.CUSTOMER_CHILD_ONE_STAR) {
                    continue;
                }
                CustomerRuleTypePojo customerRuleTypePojo = new CustomerRuleTypePojo();
                customerRuleTypePojo.setKey(type.getCode());
                customerRuleTypePojo.setValue(type.getName());
                typeList.add(customerRuleTypePojo);
            }
        }else if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            for (ClueChildTypeEnum type : ClueChildTypeEnum.values()) {
                if (type == ClueChildTypeEnum.UNKNOWN) {
                    continue;
                }
                CustomerRuleTypePojo customerRuleTypePojo = new CustomerRuleTypePojo();
                customerRuleTypePojo.setKey(type.getCode());
                customerRuleTypePojo.setValue(type.getName());
                typeList.add(customerRuleTypePojo);
            }
        }
        return typeList;
    }

    /**
     * 封装前端需要格式
     * @param groupId
     * @param groupIdNameMap
     * @return
     */
    public JSONObject getLabelValueMap(Long groupId, Map<Long, PublicGroupSeniorEntity> groupIdNameMap){
        if (Objects.isNull(groupId)){
            return new JSONObject();
        }
        if(groupId > BasicConstant.ZERO){
            JSONObject labelValueMap = new JSONObject();
            //公海分组列表
            PublicGroupSeniorEntity entity = groupIdNameMap.get(groupId);
            if (Objects.nonNull(entity)){
                StringBuilder builder = new StringBuilder(entity.getName());
                if (Objects.equals(entity.getDel(),BasicConstant.ONE)){
                    builder.append(StringConstant.DELETED);
                }else if(Objects.equals(entity.getStatus(),BasicConstant.ZERO) && Objects.equals(entity.getDel(),BasicConstant.ZERO) ){
                    builder.append(StringConstant.NOT_ENABLED);
                }
                labelValueMap.put("label",builder);
                labelValueMap.put("value",groupId);
            }
            return labelValueMap;
        }else {
            JSONObject labelValueMap = new JSONObject();
            //拿固定的分组
            labelValueMap.put("label", SeniorFixedGroupEnum.getLabelById(groupId));
            labelValueMap.put("value",groupId);
            return labelValueMap;
        }
    }

    /**
     * 退回转移
     * @param businessType 业务类型
     * @param filterArray 筛选条件：1：所有客户统一设置 ，2：根据客户条件设置
     * @param triggerArray 触发条件：1：定时退回，2、当日退回
     * @param chooseArray 触发条件选择类型：1：无新建跟进，2：无新建机会，3、无新建合同、4：无成交客户 5：未转换客户（线索）
     */
     public void addFixedTypeByBusinessType(Integer businessType, JSONArray filterArray, JSONArray triggerArray, JSONArray chooseArray){
        JSONObject triggerObj1 = new JSONObject();
        JSONObject triggerObj2 = new JSONObject();
        triggerObj1.put("label","定时退回");
        triggerObj1.put("value",BasicConstant.ONE);
        triggerObj2.put("label","当日退回");
        triggerObj2.put("value",BasicConstant.TWO);
        triggerArray.add(triggerObj1);
        triggerArray.add(triggerObj2);

        JSONObject filterObj1 = new JSONObject();
        JSONObject filterObj2 = new JSONObject();
        if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
            filterObj1.put("label","所有客户统一设置");
            filterObj1.put("value",BasicConstant.ONE);
            filterObj2.put("label","根据客户条件设置");
            filterObj2.put("value",BasicConstant.TWO);
            List<CustomerSeniorBackChildEnum> customerChildEnums = Arrays.asList(CustomerSeniorBackChildEnum.CUSTOMER_NO_COMMUNICATE,
                    CustomerSeniorBackChildEnum.CUSTOMER_NO_CONTRACT,CustomerSeniorBackChildEnum.CUSTOMER_NO_OPPORTUNITY);
            for (CustomerSeniorBackChildEnum childEnum : customerChildEnums){
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("label",childEnum.getName());
                jsonObject.put("value",childEnum.getCode());
                chooseArray.add(jsonObject);
            }
        }else if(Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())){
            filterObj1.put("label","所有线索统一设置");
            filterObj1.put("value",BasicConstant.ONE);
            filterObj2.put("label","根据线索条件设置");
            filterObj2.put("value",BasicConstant.TWO);
            List<ClueSeniorBackChildEnum> clueChildEnums = Arrays.asList(ClueSeniorBackChildEnum.CLUE_NO_COMMUNICATE,ClueSeniorBackChildEnum.CLUE_NO_TRANSFORM_CUSTOMER);
            for (ClueSeniorBackChildEnum childEnum : clueChildEnums){
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("label",childEnum.getName());
                jsonObject.put("value",childEnum.getCode());
                chooseArray.add(jsonObject);
            }
        }
        filterArray.add(filterObj1);
        filterArray.add(filterObj2);
    }



    /**
     * 添加固定的分组
     * @param groupTree
     * @param isApplyScore 是否试用范围
     * @param businessType 业务类型
     * @param type 规则类型
     */
    public JSONArray addFixedGroup(JSONArray groupTree,boolean isApplyScore, Integer businessType,Integer type){
        JSONArray allGroupTree = new JSONArray();
        JSONObject nowJson = new JSONObject();
        JSONObject preJson = new JSONObject();
        String name = SeniorFixedGroupEnum.ALL_CUSTOMER_GROUP.getLabel();
        Long id = SeniorFixedGroupEnum.ALL_CUSTOMER_GROUP.getId();
        if (Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())){
            name = SeniorFixedGroupEnum.ALL_CLUE_GROUP.getLabel();
            id = SeniorFixedGroupEnum.ALL_CLUE_GROUP.getId();
        }
        JSONObject specifiedJson = new JSONObject();
        if (isApplyScore){
            nowJson.put("label", name);
            nowJson.put("id",id);
            nowJson.put("value",id);
            nowJson.put("groupType",BasicConstant.ONE);
            nowJson.put("level",0);
            nowJson.put("sort",0);
            nowJson.put("children",groupTree);
            nowJson.put("parentId", -1);
            allGroupTree.add(nowJson);
        }else {
            //自动转移不需要添加当前分组
            if (!Objects.equals(type,CustomerSeniorRuleTypeEnum.TRANSFER_RULE.getCode())){
                nowJson.put("label",SeniorFixedGroupEnum.CURRENT_GROUP.getLabel());
                nowJson.put("id",SeniorFixedGroupEnum.CURRENT_GROUP.getId());
                nowJson.put("value",SeniorFixedGroupEnum.CURRENT_GROUP.getId());
                allGroupTree.add(nowJson);
            }
            preJson.put("label",SeniorFixedGroupEnum.PREVIOUS_GROUP.getLabel());
            preJson.put("id",SeniorFixedGroupEnum.PREVIOUS_GROUP.getId());
            preJson.put("value",SeniorFixedGroupEnum.PREVIOUS_GROUP.getId());
            specifiedJson.put("label",SeniorFixedGroupEnum.APPOINT_GROUP.getLabel());
            specifiedJson.put("id",SeniorFixedGroupEnum.APPOINT_GROUP.getId());
            specifiedJson.put("disabled",true);
            specifiedJson.put("children",groupTree);
            allGroupTree.add(preJson);
            allGroupTree.add(specifiedJson);
        }
        return allGroupTree;
    }


    /**
     * 高级模式下 最大客户数、前负责人、捞取频率 初始化
     * @param corpid
     * @param businessType
     * @param type
     */
    public void initSeniorBackEntity(String corpid,Integer businessType,Integer type,Long formId,String userId){
        TransferBackRuleSeniorEntity seniorEntity = new TransferBackRuleSeniorEntity();
        seniorEntity.setCorpid(corpid);
        seniorEntity.setJsonData(new JSONArray());
        if(Objects.equals(type, CustomerSeniorRuleTypeEnum.MAX_CUSTOMER_NUM_RULE.getCode())){
            JSONArray jsonArray = new JSONArray();
            Object o = initPublicRule(businessType, type, true);
            jsonArray.add(o);
            seniorEntity.setRuleValue(jsonArray);
        }else if(Objects.equals(type,CustomerSeniorRuleTypeEnum.PRE_PRINCIPAL_RULE.getCode()) || Objects.equals(type,CustomerSeniorRuleTypeEnum.GAIN_RATE_RULE.getCode())){
            Object o = initPublicRule(businessType, type, true);
            seniorEntity.setRuleValue(JSON.parseArray(JSON.toJSONString(o)));
        } else {
            seniorEntity.setRuleValue(new JSONArray());
        }
        seniorEntity.setType(type);
        seniorEntity.setFormId(formId);
        seniorEntity.setBusinessType(businessType);
        seniorEntity.setStatus(BasicConstant.ONE);
        seniorEntity.setCreatorId(userId);
        try {
            transferBackRuleSeniorModel.insert(seniorEntity);
        }catch (Exception e){
            LOG.error("公海高级模式规则初始化失败",e);
        }
    }

    /**
     * 标准模式下 最大客户数、前负责人、捞取频率 初始化
     * @param corpid
     * @param businessType
     * @param type
     */
    public void initCustomerRuleEntity(String corpid,Integer type,Integer businessType){
        CustomerRuleEntity customerRule = new CustomerRuleEntity();
        customerRule.setCorpid(corpid);
        customerRule.setRuleType(type);
        customerRule.setStatus(BasicConstant.ONE);
        try {
            Object o = initPublicRule(businessType, type, false);
            customerRule.setRuleValue(o.toString());
            customerRuleModel.insert(customerRule);
        }catch (Exception e){
            LOG.error("客户公海标准模式规则初始化失败",e);
        }
    }

    /**
     * 标准模式下 最大线索数、前负责人、捞取频率 初始化
     * @param corpid
     * @param businessType
     * @param type
     */
    public void initClueRuleEntity(String corpid,Integer type,Integer businessType){
        ClueRuleEntity clueRule = new ClueRuleEntity();
        clueRule.setCorpid(corpid);
        clueRule.setRuleType(type);
        clueRule.setDel(BasicConstant.ZERO);
        clueRule.setStatus(BasicConstant.ONE);
        try {
            Object o = initPublicRule(businessType, type, false);
            clueRule.setRuleValue(o.toString());
            clueRuleModel.insert(clueRule);
        }catch (Exception e){
            LOG.error("线索公海标准模式规则初始化失败",e);
        }
    }

    public Integer getRemindTimeByAlias(String corpid,String alias){
        CompanyConfigEntity companyConfig = companyConfigModel.getConfigEntity(corpid,alias);
        if (companyConfig != null) {
            return StringUtil.toInt(companyConfig.getConfigValue(), 3);
        }
        return Integer.valueOf(CompanyConfigEnum.PUBLIC_RULE_REMIND_TIME.getValue());
    }

    /**
     * 存库所需：格式化特殊员工users - 从复杂->结构简单
     * @param jsonArray
     */
    public void formatSaveUsers(JSONArray jsonArray) {
        for (Object ruleObj : jsonArray) {
            JSONArray userArray = FastJsonHelper.getJsonArrayOrDefault((JSONObject) ruleObj, "users", new JSONArray());
            if (CollectionsUtil.isEmpty(userArray)) {
                continue;
            }
            List<String> users = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<String> depts = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<String> roles = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (Object userObj : userArray) {
                String property = ((JSONObject) userObj).getString("property");
                String id = ((JSONObject) userObj).getString("id");
                if (Objects.equals(property, OptionalRangeEnum.USER.getValue())) {
                    users.add(id);
                } else if (Objects.equals(property, OptionalRangeEnum.DEPT.getValue())) {
                    depts.add(id);
                } else if (Objects.equals(property, OptionalRangeEnum.ROLE.getValue())) {
                    roles.add(id);
                }
            }
            ((JSONObject) ruleObj).put("users", users);
            if (!depts.isEmpty()) {
                // 因为上面的人员是直接存数组的，所以部门这里为了区分只能是另放在depts里面
                ((JSONObject) ruleObj).put("depts", depts);
            }
            if (!roles.isEmpty()) {
                // 因为上面的人员是直接存数组的，所以角色这里为了区分只能是另放在roles里面
                ((JSONObject) ruleObj).put("roles", roles);
            }
        }
    }

    /**
     * 前端所需：格式化特殊员工users - 从简单->结构负责
     * @param jsonArray 退回规则
     * @param corpid 公司id
     */
    public void formatReturnUsers(JSONArray jsonArray,String corpid){
        for (Object triggerObj : jsonArray) {
            JSONObject ruleJson = (JSONObject) triggerObj;
            List<OptionalRangeEntity> optionalRangeEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            JSONArray userArr = FastJsonHelper.getJsonArrayOrDefault(ruleJson, "users", new JSONArray());
            JSONArray deptArr = FastJsonHelper.getJsonArrayOrDefault(ruleJson, "depts", new JSONArray());
            JSONArray roleArr = FastJsonHelper.getJsonArrayOrDefault(ruleJson, "roles", new JSONArray());
            String value = ruleJson.getString("value");
            if (StringUtil.isNotEmpty(value)){
                ruleJson.put("value",Long.valueOf(value));
            }
            if (userArr != null) {
                List<String> idList = JSON.parseArray(userArr.toJSONString(), String.class);
                List<UserEntity> users = userModel.getByUserId(idList, corpid);
                for (UserEntity userEntity : users) {
                    OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
                    optionalRangeEntity.setId(userEntity.getUserId());
                    optionalRangeEntity.setName(userEntity.getName());
                    optionalRangeEntity.setEditable(1);
                    optionalRangeEntity.setProperty(OptionalRangeEnum.USER.getValue());
                    optionalRangeEntityList.add(optionalRangeEntity);
                }
                if (deptArr != null) {
                    // 因为前端回显人员和部门是用同一个组件，所以这里部门也加在人员一起
                    List<Long> deptIds = JSON.parseArray(deptArr.toJSONString(), Long.class);
                    List<DepartmentEntity> deptEntitys = departmentModel.getByDepIdIn(corpid, deptIds);
                    for (DepartmentEntity departmentEntity : deptEntitys) {
                        OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
                        optionalRangeEntity.setId(departmentEntity.getId().toString());
                        optionalRangeEntity.setName(departmentEntity.getName());
                        optionalRangeEntity.setEditable(1);
                        optionalRangeEntity.setProperty(OptionalRangeEnum.DEPT.getValue());
                        optionalRangeEntityList.add(optionalRangeEntity);
                    }
                }
                if (roleArr != null) {
                    // 因为前端回显人员和部门是用同一个组件，所以这里角色也加在人员一起
                    List<Integer> roleIds = JSON.parseArray(roleArr.toJSONString(), Integer.class);
                    List<RoleEntity> roleEntities = roleModel.getByRoleIdIn(corpid, roleIds);
                    for (RoleEntity roleEntity : roleEntities) {
                        OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
                        optionalRangeEntity.setId(roleEntity.getId().toString());
                        optionalRangeEntity.setName(roleEntity.getRoleName());
                        optionalRangeEntity.setEditable(1);
                        optionalRangeEntity.setProperty(OptionalRangeEnum.ROLE.getValue());
                        optionalRangeEntityList.add(optionalRangeEntity);
                    }
                }
            }
            if (CollectionsUtil.isNotEmpty(optionalRangeEntityList)){
                ruleJson.put("users", optionalRangeEntityList);
            }
        }
    }



    /**
     * 获取指定表单开启的标签id
     * @param corpid 公司id
     * @param formIdIn 表单id
     * @return
     */
    public Map<Long, List<Long>> getLabelIds4FormId(String corpid,List<Long> formIdIn){
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<Long>> formIdLabelIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //获取表单名
        param.put("corpid", corpid);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("formIdIn", formIdIn);
        param.put("columns", "id,form_id");
        List<LabelEntity> labelEntityList = labelModel.findEntitys(param);
        if (CollectionsUtil.isNotEmpty(labelEntityList)){
            Map<Long, List<LabelEntity>> collect  = labelEntityList.stream().collect(Collectors.groupingBy(LabelEntity::getFormId));
            for(Map.Entry<Long,List<LabelEntity>> entry : collect.entrySet()){
                List<Long> labelIds = new ArrayList<>();
                entry.getValue().forEach(item -> labelIds.add(item.getId()));
                formIdLabelIdMap.put(entry.getKey(),labelIds);
            }
        }
        return formIdLabelIdMap;
    }

    /**
     * 根据标签设置：获取前端所需要的标签数据
     * @param corpid
     * @param labelIds 标签id
     * @return
     */
    public List<PublicRuleLabelPojo> getRuleLabelPojos(String corpid,List<Long> labelIds){
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> formIdList = new ArrayList<>();
        List<LabelEntity> labelEntityList = new ArrayList<>();
        List<PublicRuleLabelPojo> ruleLabelPojos = new ArrayList<>();
        Map<Long, String> formIdAndName = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //获取标签名
        if (CollectionsUtil.isNotEmpty(labelIds)) {
            param.put("corpid", corpid);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("idIn", labelIds);
            param.put("columns", "id,lable_name,form_id,lable_color");
            labelEntityList = labelModel.findEntitys(param);
            if (CollectionsUtil.isNotEmpty(labelEntityList)) {
                labelEntityList.forEach(item -> formIdList.add(item.getFormId()));
            }
        }
        //获取表单名
        if (CollectionsUtil.isNotEmpty(formIdList)) {
            Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid", corpid);
            map.put("del", DelEnum.NORMAL.getDel());
            map.put("idIn", formIdList);
            List<PaasFormEntityExt> formEntityExtList = paasFormModel.findEntitys(map);
            formIdAndName = formEntityExtList.stream().collect(Collectors.toMap(PaasFormEntityExt::getId, PaasFormEntityExt::getName));
        }
        if (CollectionsUtil.isEmpty(labelEntityList)){
            return ruleLabelPojos;
        }
        for (LabelEntity entity : labelEntityList) {
            if (Objects.isNull(entity)) {
                continue;
            }
            Long formId = entity.getFormId();
            String name = entity.getName();
            if (formIdAndName.containsKey(formId)) {
                String formName = formIdAndName.get(formId);
                // 名称一样的，需要在给标签名称改为“表单名称/标签名称”
                if (StringUtil.isNotEmpty(formName)) {
                    name = formName + "/" + name;
                    entity.setName(name);
                }
            }
            PublicRuleLabelPojo ruleLabelPojo = new PublicRuleLabelPojo();
            BeanUtil.copyProperties(entity, ruleLabelPojo, true);
            ruleLabelPojos.add(ruleLabelPojo);
        }
        return ruleLabelPojos;
    }
    /**
     *  多公司执行定时任务:标准模式下 - 去除开了高级模式的公司，高级模式下 - 去除未开启高级模式的公司
     * @param corpids 公司列表
     * @param isCustomerSenior 是否公海高级模式
     * @param businessType 区分客户和线索
     */
    public void removeCorpidsByModel(List<String> corpids,Boolean isCustomerSenior,Integer businessType){
        if (CollectionsUtil.isNotEmpty(corpids)){
            if (isCustomerSenior){
                corpids.removeIf(item -> {
                    try {
                        if (Objects.equals(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(),businessType)){
                            return !commonHelp.isCustomerPublicPoolSeniorModel(item);
                        }else {
                            return !commonHelp.isCluePublicPoolSeniorModel(item);
                        }
                    } catch (XbbException e) {
                        e.printStackTrace();
                    }
                    return false;
                });
            }else {
                corpids.removeIf(item -> {
                    try {
                        if (Objects.equals(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(),businessType)){
                            return commonHelp.isCustomerPublicPoolSeniorModel(item);
                        }else {
                            return commonHelp.isCluePublicPoolSeniorModel(item);
                        }
                    } catch (XbbException e) {
                        e.printStackTrace();
                    }
                    return false;
                });
            }
        }
    }


    /**
     * 最大客户（线索）数退回规则、捞取频率规则、前负责人规则 - 兼容标准模式老逻辑 规则实体复制
     * @param ruleSeniorEntity
     * @param customerRule
     * @param clueRule
     * @param businessType
     */
    public void copyRuleEntity(TransferBackRuleSeniorEntity ruleSeniorEntity, CustomerRuleEntity customerRule, ClueRuleEntity clueRule, Integer businessType){
        Integer ruleType = ruleSeniorEntity.getType();
        JSONArray ruleValueArray = ruleSeniorEntity.getRuleValue();
        if (Objects.equals(businessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
            BeanUtil.copyProperties(ruleSeniorEntity,customerRule);
            if(CollectionsUtil.isEmpty(ruleValueArray)){
                customerRule.setStatus(BasicConstant.ZERO);
            }
            if (Objects.equals(ruleType, CustomerSeniorRuleTypeEnum.MAX_CUSTOMER_NUM_RULE.getCode())){
                customerRule.setRuleType(CustomerRuleEnum.MAX_CUSTOMER_NUM_RULE.getCode());
                customerRule.setRuleValue(JSON.toJSONString(CollectionsUtil.isNotEmpty(ruleValueArray) ? ruleValueArray.getJSONObject(0) : new JSONObject()));
            }else if (Objects.equals(ruleType, CustomerSeniorRuleTypeEnum.PRE_PRINCIPAL_RULE.getCode())){
                customerRule.setRuleType(CustomerRuleEnum.PRE_PRINCIPAL_RULE.getCode());
                customerRule.setRuleValue(JSON.toJSONString(ruleValueArray));
            }else if (Objects.equals(ruleType, CustomerSeniorRuleTypeEnum.GAIN_RATE_RULE.getCode())){
                customerRule.setRuleType(CustomerRuleEnum.GAIN_RATE_RULE.getCode());
                customerRule.setRuleValue(JSON.toJSONString(ruleValueArray));
            }
        }else if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            BeanUtil.copyProperties(ruleSeniorEntity,clueRule);
            if(CollectionsUtil.isEmpty(ruleValueArray)){
                clueRule.setStatus(BasicConstant.ZERO);
            }
            if (Objects.equals(ruleType, ClueSeniorRuleTypeEnum.MAX_CLUE_NUM_RULE.getCode())){
                clueRule.setRuleType(ClueRuleEnum.MAX_CLUE_NUM_RULE.getCode());
                clueRule.setRuleValue(JSON.toJSONString(CollectionsUtil.isNotEmpty(ruleValueArray) ? ruleValueArray.getJSONObject(0) : new JSONObject()));
            }else if (Objects.equals(ruleType, ClueSeniorRuleTypeEnum.PRE_PRINCIPAL_RULE.getCode())){
                clueRule.setRuleType(ClueRuleEnum.PRE_PRINCIPAL_RULE.getCode());
                clueRule.setRuleValue(JSON.toJSONString(ruleValueArray));
            }else if (Objects.equals(ruleType, ClueSeniorRuleTypeEnum.GAIN_RATE_RULE.getCode())){
                clueRule.setRuleType(ClueRuleEnum.GAIN_RATE_RULE.getCode());
                clueRule.setRuleValue(JSON.toJSONString(ruleValueArray));
            }
        }
    }

    /**
     * 公海高级模式 - 兼容老逻辑，高级模式规则实体转标准模式实体
     * @param corpid
     * @param businessType
     * @param customerRuleEntityList
     * @param clueRuleEntityList
     * @throws XbbException
     */
    public void getPublicSeniorRuleList(String corpid ,Integer businessType,List<CustomerRuleEntity> customerRuleEntityList,List<ClueRuleEntity> clueRuleEntityList) throws XbbException {
        if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
            if (commonHelp.isCustomerPublicPoolSeniorModel(corpid)){
                List<TransferBackRuleSeniorEntity> seniorEntityList = transferBackRuleSeniorModel.getSpecialRules(corpid, businessType);
                if (CollectionsUtil.isNotEmpty(seniorEntityList)){
                    //兼容老逻辑
                    for (TransferBackRuleSeniorEntity seniorEntity : seniorEntityList){
                        CustomerRuleEntity customerRule = new CustomerRuleEntity();
                        copyRuleEntity(seniorEntity,customerRule,null,businessType);
                        customerRuleEntityList.add(customerRule);
                    }
                }
            }else {
                List<CustomerRuleEntity> ruleEntityList = customerRuleModel.getSpecialRules(corpid);
                customerRuleEntityList.addAll(ruleEntityList);
            }
        }else if (Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())) {
            if (commonHelp.isCluePublicPoolSeniorModel(corpid)){
                List<TransferBackRuleSeniorEntity> seniorEntityList = transferBackRuleSeniorModel.getSpecialRules(corpid, businessType);
                if (CollectionsUtil.isNotEmpty(seniorEntityList)){
                    //兼容老逻辑
                    for (TransferBackRuleSeniorEntity seniorEntity : seniorEntityList){
                        ClueRuleEntity clueRule = new ClueRuleEntity();
                        copyRuleEntity(seniorEntity,null,clueRule,businessType);
                        clueRuleEntityList.add(clueRule);
                    }
                }
            }else {
                List<ClueRuleEntity> ruleEntityList = clueRuleModel.getSpecialRules(corpid);
                clueRuleEntityList.addAll(ruleEntityList);
            }
        }
    }

    /**
     * 公海高级模式 为了兼容老逻辑 - 根据类型获取高级模式规则，在转成标准模式规则
     * @param corpid 公司id
     * @param ruleType 规则类型
     * @param businessType 业务类型
     */
    public CustomerRuleEntity getCustomerRule(String corpid,Integer ruleType,Integer businessType){
        CustomerRuleEntity customerRule = null;
        List<TransferBackRuleSeniorEntity> seniorEntityList = transferBackRuleSeniorModel.getTransferBackRuleByType(corpid, null, businessType, Arrays.asList(ruleType), null);
        if (CollectionsUtil.isNotEmpty(seniorEntityList)){
            customerRule = new CustomerRuleEntity();
            TransferBackRuleSeniorEntity seniorEntity = seniorEntityList.get(BasicConstant.ZERO);
            copyRuleEntity(seniorEntity,customerRule,null,businessType);
        }
        return customerRule;
    }

    /**
     * 公海高级模式 为了兼容老逻辑 - 根据类型获取高级模式规则，在转成标准模式规则
     * @param corpid 公司id
     * @param ruleType 规则类型
     * @param businessType 业务类型
     */
    public ClueRuleEntity getClueRule(String corpid,Integer ruleType,Integer businessType){
        ClueRuleEntity clueRule = null;
        List<TransferBackRuleSeniorEntity> seniorEntityList = transferBackRuleSeniorModel.getTransferBackRuleByType(corpid, null, businessType, Arrays.asList(ruleType), null);
        if (CollectionsUtil.isNotEmpty(seniorEntityList)){
            clueRule = new ClueRuleEntity();
            TransferBackRuleSeniorEntity seniorEntity = seniorEntityList.get(BasicConstant.ZERO);
            copyRuleEntity(seniorEntity,null,clueRule,businessType);
        }
        return clueRule;
    }

    /**
     * 初始化公司需要初始化公海池规则
     * @param businessType 业务类型
     * @param ruleType 规则类型
     * @param isSeniorModel 是否公海高级模式
     * @return
     */
    public Object initPublicRule(Integer businessType,Integer ruleType,boolean isSeniorModel){
        String status = "customerStatus";
        if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            status = "clueStatus";
        }
        //标准模式下 是否前负责人和捞取频率规则
        boolean isCustomer = Objects.equals(businessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())
                && (Objects.equals(ruleType,CustomerRuleEnum.PRE_PRINCIPAL_RULE.getCode())
                || Objects.equals(ruleType,CustomerRuleEnum.GAIN_RATE_RULE.getCode()));
        boolean isClue = Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())
                && (Objects.equals(ruleType,ClueRuleEnum.PRE_PRINCIPAL_RULE.getCode())
                || Objects.equals(ruleType,ClueRuleEnum.GAIN_RATE_RULE.getCode()));
        if (isSeniorModel){
            //高级模式下 是否前负责人和捞取频率规则
            isCustomer = Objects.equals(businessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())
                    && (Objects.equals(ruleType,CustomerSeniorRuleTypeEnum.PRE_PRINCIPAL_RULE.getCode())
                    || Objects.equals(ruleType,CustomerSeniorRuleTypeEnum.GAIN_RATE_RULE.getCode()));
            isClue = Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())
                    && (Objects.equals(ruleType,ClueSeniorRuleTypeEnum.PRE_PRINCIPAL_RULE.getCode())
                    || Objects.equals(ruleType,ClueSeniorRuleTypeEnum.GAIN_RATE_RULE.getCode()));
        }
        if (isCustomer || isClue){
            JSONArray ruleValueArr = new JSONArray();
            JSONObject arrayJson = new JSONObject();
            arrayJson.put("value",7);
            ruleValueArr.add(arrayJson);
            return ruleValueArr;
        }else {
            JSONObject ruleValue = new JSONObject();
            JSONArray restrictArr = new JSONArray();
            JSONObject jsonObject = new JSONObject();
            JSONArray jsonArray = new JSONArray();
            JSONObject arrayJson = new JSONObject();
            arrayJson.put("key",BasicConstant.ZERO);
            arrayJson.put("value",14);
            jsonArray.add(arrayJson);
            jsonObject.put("array",jsonArray);
            restrictArr.add(jsonObject);
            JSONObject backRuleJson = new JSONObject();
            backRuleJson.put("sort",new JSONArray());
            backRuleJson.put("backType",BasicConstant.ONE);
            ruleValue.put("type",BasicConstant.ZERO);
            ruleValue.put("label",new JSONArray());
            ruleValue.put("contract",BasicConstant.ZERO);
            ruleValue.put("opportunity",BasicConstant.ZERO);
            ruleValue.put("restrict",restrictArr);
            ruleValue.put("backRule",backRuleJson);
            ruleValue.put(status,new JSONArray());
            return ruleValue;
        }
    }

    /**
     * 获取分组规则管理员和成员列表C
     * @param scopeRule 管理员或成员规则
     * @param corpid    公司id
     * @param idToPushGroupMap 分组id和推送列表
     * @param groupSeniorId 分组id
     */
    public void getUserIdsByScopeRule(JSONArray scopeRule,String corpid,Map<Long, Set<String>> idToPushGroupMap,Long groupSeniorId){
        if (CollectionsUtil.isNotEmpty(scopeRule)){
            Set<String> set = new HashSet<>();
            List<String> users = new ArrayList<>();
            List<Long> depts = new ArrayList<>();
            List<Integer> roles = new ArrayList<>();
            for (Object o : scopeRule){
                JSONObject admin = (JSONObject) o;
                try {
                    String property = FastJsonHelper.getStringOrDefault(admin, "property", "");
                    String id = FastJsonHelper.getStringOrDefault(admin, "id", "");
                    if(Objects.equals(property,"user")){
                        users.add(id);
                    }
                    if(Objects.equals(property,"dept")){
                        depts.add(Long.parseLong(id));
                    }
                    if(Objects.equals(property,"role")){
                        roles.add(Integer.parseInt(id));
                    }
                } catch (Exception e) {
                    LOG.warn("获取分组管理员或成员，解析失败",e);
                }
            }
            List<String> roleUserIds = new ArrayList<>();
            List<String> deptUserIds = new ArrayList<>();
            if (CollectionsUtil.isNotEmpty(roles)){
                roleUserIds = userModel.getUserIdsByRoles(corpid, roles);
            }
            if (CollectionsUtil.isNotEmpty(depts)){
                deptUserIds = userModel.getUserIdsRecursionDep(depts,corpid);
            }
            set.addAll(roleUserIds);
            set.addAll(deptUserIds);
            set.addAll(users);
            idToPushGroupMap.put(groupSeniorId,set);
        }
    }


    /**
     * 切换公海模式过程过，不能修改高级模式和标准模式的配置
     * @param corpid 公司id
     * @param businessType 业务类型
     * @return
     */
    public boolean checkChangeSeniorStatus(String corpid,Integer businessType) {
        boolean flag = false;
        String changeSeniorComplete = RedisPrefixConstant.CUSTOMER_PUBLIC_POOL_MODEL_CHANGE_SENIOR_COMPLETE;
        if (Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())) {
            changeSeniorComplete = RedisPrefixConstant.CLUE_PUBLIC_POOL_MODEL_CHANGE_SENIOR_COMPLETE;
        }
        String value = paasRedisHelper.getValue(changeSeniorComplete, corpid);
        if (Objects.isNull(value) || Objects.equals(value,BasicConstant.THREE.toString())){
            flag = true;
        }
        return flag;
    }

    /**
     * 更新客户和线索公海池“退”字标签
     * @param corpid 公司id
     * @param dataId 客户 线索id
     * @param memo 提醒内容
     * @param businessType 业务类型
     * @throws XbbException
     */
    public void updateTagLink(String corpid, Long dataId, String memo,Integer businessType) throws XbbException {
        TagTypeEnum tagTypeEnum = TagTypeEnum.PUBLIC_CUSTOMER_RULE;
        if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            tagTypeEnum = TagTypeEnum.PUBLIC_CLUE_RULE;
        }
        TagLinkEntity tagLink = tagLinkModel.getTagByTagType(corpid, tagTypeEnum.getCode(), dataId);
        TagEntity returnPublicTag = tagModel.findReturnPublicTag(tagTypeEnum.getCode());
        if(StringUtil.isEmpty(memo)){
            if (tagLink == null){
                return ;
            }
            List<Long> refIdIn = new ArrayList<>();
            refIdIn.add(dataId);
            //该客户的所有主负责人都不需要退回公海提醒,删除客户标签
            tagLinkModel.deleteTagByTagTypeAndRefIdIn(corpid, TagTypeEnum.PUBLIC_CUSTOMER_RULE.getCode(), refIdIn);
        }else {
            if (memo.indexOf(I18nMessageUtil.getMessage(I18nStringConstant.WILL_RETURN_CUSTOMER_PUBLIC_N)) > -1) {
                memo = memo.replaceFirst(I18nMessageUtil.getMessage(I18nStringConstant.WILL_RETURN_CUSTOMER_PUBLIC_N), I18nMessageUtil.getMessage(I18nStringConstant.WILL_RETURN_CUSTOMER_PUBLIC_1));
            }
            if(tagLink == null){
                tagLink = new TagLinkEntity(corpid, "", returnPublicTag, dataId, XbbRefTypeEnum.CUSTOMER, memo);
            }else{
                tagLink.setMemo(memo);
            }
            tagLinkModel.save(tagLink);
        }
    }

    /**
     * 分页 获取公海池中的客户、线索数据id
     * @param gtId 大于id
     * @param corpid 公司id
     * @param formId 表单id
     * @param isPublic 是否公海客户、线索
     * @param businessType 业务类型
     * @param pageSize 一页数量
     * @return
     */
    public List<Long> getDataIdList4Public(Long gtId,String corpid,Long formId,Integer isPublic,Integer businessType,Integer pageSize) throws XbbException {
        List<Long> dataIdIn = new ArrayList<>();
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, SaasMarkEnum.SAAS.getCode());
        String isPublicAttr = CustomerManagementEnum.getEsAttr4Keyword(CustomerManagementEnum.IS_PUBLIC);
        if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            isPublicAttr = ClueEnum.getEsAttr4Keyword(ClueEnum.IS_PUBLIC);
        }
        SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,BasicConstant.ZERO));
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("formId",formId));
        boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.PASS.getType(), FlowStatusEnum.NOT_NEED_APPROVAL.getType())));
        boolQueryBuilder.filter(termQuery(isPublicAttr,isPublic));
        if (Objects.nonNull(gtId)) {
            boolQueryBuilder.filter(rangeQuery(FieldTypeEnum.DATAID.getAlias()).gt(gtId));
        }
        sourceBuilder.query(boolQueryBuilder);
        //处理显示字段 id
        EsUtil.setFieldListNoMerge(sourceBuilder, Arrays.asList(BusinessConstant.ID));
        //只查第一页
        EsUtil.setPage(sourceBuilder, 1, pageSize);
        //id升序
        sourceBuilder.sort(new FieldSortBuilder(BasicConstant.ID).order(SortOrder.ASC));
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<RuleSeniorEntity> aggregatedPage = xbbElasticsearchRestTemplate.queryForPages(null, searchRequest, RuleSeniorEntity.class);
        if (aggregatedPage != null){
            List<RuleSeniorEntity> list = aggregatedPage.getContent();
            if (CollectionsUtil.isNotEmpty(list)){
                list.forEach(item -> dataIdIn.add(item.getId()));
            }
        }
        return dataIdIn;
    }

    /**
     * @description 获取客户、线索每个模板公海池的总数
     * @author yanglei
     * @date 2023/2/20 19:11
     * @param corpid        公司id
     * @param businessType  业务类型
     * @param formId        表单id
     * @return Long
     */
    public Long getPublicCountByForm(String corpid,Integer businessType,Long formId) throws XbbException {
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, SaasMarkEnum.SAAS.getCode());
        String isPublicAttr = CustomerManagementEnum.getEsAttr4Keyword(CustomerManagementEnum.IS_PUBLIC);
        if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            isPublicAttr = ClueEnum.getEsAttr4Keyword(ClueEnum.IS_PUBLIC);
        }
        SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,BasicConstant.ZERO));
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("formId",formId));
        boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.PASS.getType(), FlowStatusEnum.NOT_NEED_APPROVAL.getType())));
        boolQueryBuilder.filter(termQuery(isPublicAttr,BasicConstant.ONE));
        sourceBuilder.query(boolQueryBuilder);
        searchRequest.source(sourceBuilder);
        return xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);

    }

    /**
     * 获取表单解释的字段是否启用或已删除
     * @param corpid 公司id
     * @return Map<String,Integer>
     * @throws XbbException
     */
    public Map<Long,Map<String, Integer>> getExplainOpenMap(String corpid,List<Long> formIdIn) throws XbbException {
        Map<Long,Map<String, Integer>> formIdExplainMap = new HashMap<>();
        List<PaasFormExplainEntity> list = paasFormExplainModel.getByFormIdIn(formIdIn,corpid);
        if (CollectionsUtil.isNotEmpty(list)){
            list.forEach(explainEntity -> {
                List<FieldAttrEntity> explainList = JsonHelperUtil.parseArray(explainEntity.getExplains(), FieldAttrEntity.class);
                Map<String, Integer> explainMap = explainList.stream().collect(Collectors.toMap(FieldAttrEntity::getAttr, FieldAttrEntity::getIsOpen));
                formIdExplainMap.put(explainEntity.getFormId(),explainMap);
            });
        }
        return formIdExplainMap;
    }



    /**
     * 业务规则和工作流使用，合同签订日期更新要同步更新关联客户的合同最近签订日期字段
     * @param updateList 需要更新的集合
     * @param corpid 公司id
     */
    @Async(value = "signTimeThreadPool")
    public void asyncUpdateCustomerSignTime(List<UpdateDataEntity> updateList, String corpid) {
        if (CollectionsUtil.isEmpty(updateList)){
            return;
        }
        try {
            Map<Long, Long> idToSignTime = new HashMap<>();
            for(UpdateDataEntity updateData : updateList){
                Long contractId = updateData.getId();
                List<UpdateDataValueEntity> UpdateDataValueList = updateData.getData();
                for (UpdateDataValueEntity item : UpdateDataValueList){
                    //找到是否需要更新签订日期字段，一个数据找到就需要更新
                    if (Objects.equals(item.getEsKey(), ContractEnum.getAttrConnectData(ContractEnum.SIGN_TIME))){
                        idToSignTime.put(contractId,Long.parseLong(item.getValue().toString()));
                    }
                }
            }
            //需要更新的客户ids
            Set<Long> updateIdList = idToSignTime.keySet();
            if (CollectionsUtil.isEmpty(updateIdList)){
                return;
            }
            //更新操作
            List<ContractEntityExt> contractEntityExtList = contractModel.findEntitysByIdIn(corpid, BasicConstant.ZERO, new ArrayList<>(updateIdList));
            for(ContractEntityExt contract : contractEntityExtList){
                JSONObject data = contract.getData();
                if (Objects.nonNull(data) && Objects.nonNull(data.get(ContractEnum.SIGN_TIME.getAttr()))) {
                    //客户更新签订时间
                    Long newSignTime = idToSignTime.get(contract.getId());
                    Long customerId = data.getLongValue(ContractEnum.LINK_CUSTOMER.getAttr());
                    updateCustomerContractSignTime(newSignTime,corpid,customerId,contract.getId());
                }
            }
        }catch (Exception e){
            LOG.error("更新客户的合同最近签订时间失败",e);
        }
    }

    /**
     * 当个合同更新签订时间，同步更新关联客户的合同最近签订时间（隐藏逻辑）
     * @param signTime 新的签订时间
     * @param corpid 公司id
     * @param newCustomerId 关联客户id
     * @param contractId 合同id
     * @throws XbbException
     */
    public void updateCustomerContractSignTime(Long signTime,String corpid,Long newCustomerId,Long contractId) throws XbbException {
        //编辑和新建合同都要更新客户的合同签订时间
        JSONObject jsonObject = new JSONObject();
        if (Objects.nonNull(signTime)) {
            //获取最新签订时间一个合同
            List<ContractEntityExt> list = contractModel.getLatestEntityListByCustomerId(corpid, newCustomerId);
            if (CollectionsUtil.isNotEmpty(list)){
                if (list.size() > 1){
                    ContractEntityExt latestContract = list.get(0);
                    ContractEntityExt secondContract = list.get(1);
                    Long latestSignDate = latestContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                    Long secondSignDate = secondContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                    if (Objects.equals(latestContract.getId(),contractId)){
                        //说明编辑的最近的这个合同
                        if (signTime >= latestSignDate){
                            jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                        }else if(signTime > secondSignDate) {
                            jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                        }else {
                            jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), secondSignDate);
                        }
                    }else {
                        //说明编辑的其他合同
                        if (signTime > latestSignDate){
                            jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                        }
                    }
                }else {
                    ContractEntityExt latestContract = list.get(0);
                    Long latestSignDate = latestContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                    if (signTime >= latestSignDate){
                        jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                    }
                }
            }
            if (!jsonObject.isEmpty()) {
                customerModel.specialUpdate4SysDate(newCustomerId, jsonObject, corpid);
            }
        }
    }

    public void addressSearchShouldCondition(List<ConditionsEntityExt> conditionList) {
        conditionList.forEach(item -> {
            if (Objects.equals(AddressEnum.PROVINCE.getAlias(),item.getAttr()) || Objects.equals(AddressEnum.CITY.getAlias(),item.getAttr())
                    || Objects.equals(AddressEnum.DISTRICT.getAlias(),item.getAttr()) || Objects.equals(AddressEnum.ADDRESS.getAlias(),item.getAttr()) )  {
                item.setAttr(CustomerManagementEnum.ADDRESS.getAttr() + StringConstant.POINT + item.getAttr());
            }
        });
    }

    /**
     * 获取指定分组id列表
     * @param formIdAllGroupIdMap 每个表单所有的分组List
     * @param formIdOpenGroupIdMap 每个表单开启的分组idList
     * @param formIdDeleteGroupIdMap 每个表单当前删除的分组idList
     * @param formIdNoGroupMap 每个表单对应的无分组id
     * @param corpid 公司id
     * @param formIdIn 表单id
     * @return  无分组id
     */
    public void getSpecialGroupIdMap(Map<Long,List<PublicGroupSeniorEntity>> formIdAllGroupIdMap,Map<Long,List<Long>> formIdOpenGroupIdMap, Map<Long,List<Long>> formIdDeleteGroupIdMap, Map<Long, Long> formIdNoGroupMap, String corpid,List<Long> formIdIn){
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //获取表单名
        param.put("corpid", corpid);
        param.put("formIdIn", formIdIn);
        List<PublicGroupSeniorEntity> allGroupList = publicGroupSeniorModel.findEntitys(param);
        if (CollectionsUtil.isNotEmpty(allGroupList)){
            Map<Long, List<PublicGroupSeniorEntity>> collect = allGroupList.stream().collect(Collectors.groupingBy(PublicGroupSeniorEntity::getFormId));
            for(Map.Entry<Long,List<PublicGroupSeniorEntity>> entry : collect.entrySet()){
                List<Long> openGroupIdList = new ArrayList<>();
                List<Long> deleteGroupIdList = new ArrayList<>();
                Long noGroupId = 0L;
                Long formId = entry.getKey();
                for (PublicGroupSeniorEntity groupSeniorEntity : entry.getValue()) {
                    if (Objects.equals(groupSeniorEntity.getStatus(),BasicConstant.ONE) && Objects.equals(groupSeniorEntity.getDel(),BasicConstant.ZERO)){
                        openGroupIdList.add(groupSeniorEntity.getId());
                        if (Objects.equals(groupSeniorEntity.getGroupType(),BasicConstant.TWO)){
                            noGroupId = groupSeniorEntity.getId();
                        }
                    }
                    if (Objects.equals(groupSeniorEntity.getDel(),BasicConstant.ZERO)){
                        deleteGroupIdList.add(groupSeniorEntity.getId());
                    }
                }
                formIdNoGroupMap.put(formId,noGroupId);
                formIdOpenGroupIdMap.put(formId,openGroupIdList);
                formIdOpenGroupIdMap.put(formId,deleteGroupIdList);
                formIdAllGroupIdMap.put(formId,entry.getValue());
            }
        }
    }
}
